#include "Trackball.h"
//***************************************************************
//
// Created BY: JESSE SAHOTA
// COURSE: CPSC 589
//
//***************************************************************
//***********************************************
//Function Name: Trackball()
//
//Purpose: Initialize the Trackball class
//
//***********************************************
Trackball::Trackball()
{
    indentityMatrix();
}
//***********************************************
//Function Name: applyRotation
//
//Purpose: apply the rotation on the object
//
//***********************************************
void Trackball::applyRotation(){
    glMultMatrixf(rotationMatrix);
}
//***********************************************
//Function Name: setRotation
//
//Purpose: The basically set the rotation into the trackball
//-------- rotation matrix
//
//***********************************************
void Trackball::setRotation(const double &angle, const Vector &v){
    glPushMatrix();
    glLoadIdentity();
    glRotated(angle, v.getX(), v.getY(), v.getZ());
    glMultMatrixf( (GLfloat *) rotationMatrix );
    glGetFloatv(GL_MODELVIEW_MATRIX, rotationMatrix);
    glPopMatrix();
}
//***********************************************
//Function Name: startTrackball
//
//Purpose: The startup trackball rotation, calculating z coordinate
//-------- from x and y coordinate and set the current Coord with normalized
//-------- vector from x,y,z
//
//Input: x: The x position for the trackball
//------ y: The y position for the trackball
//
//***********************************************
void Trackball::startTrackball(const double &x, const double &y){
    double z = calcZCoordinate(x,y);
    if (z > 0.0){
        Vector temp(x,y,z);
        setCurrCoord(temp.normalize());
    }
}
//***********************************************
//Function Name: trackballMovement
//
//Purpose: This track the move, by getting x and y and calculating z
//-------- then forms the a new vector, then do crossproduct with the current
//-------- coordinate to get the current vector and dot product of the product
//-------- for angle. Then set the rotation
//
//Input: x: The x position for the trackball
//------ y: The y position for the trackball
//
//***********************************************
void Trackball::trackballMovement(const double &x, const double &y){
    double z = calcZCoordinate(x,y);
    if (z > 0.0){
        Vector temp(x,y,z);
        temp.unit();
        Vector prodVector = currentCoordinate.cross(temp);
        prodVector.unit();
        double angle = prodVector.dotProduct(prodVector);
        setRotation(angle, prodVector);

        currentCoordinate = temp;

    }
}
//***********************************************
//Function Name: setCurrCoord
//
//Purpose: set the current coordinate with new coordinate
//
//***********************************************
void Trackball::setCurrCoord(const Vector &v){
    currentCoordinate = v;
}
//***********************************************
//Function Name: indentityMatrix
//
//Purpose: setting the rotationMatrix into an identity matrix
//-------- just like loadIndentity for openGL
//
//***********************************************
void Trackball::indentityMatrix(){
    for(int i =0; i < 4; i++){
        for(int n=0; n<4; n++){
            if( i == n){
                rotationMatrix[i*4 + n] = 1.0;
            }else{
                rotationMatrix[i*4 + n] = 0.0;
            }
        }
    }
}
//***********************************************
//Function Name: calcZCoordinate
//
//Purpose: This calculate z Coordinate of the spherical trackball
//
//Input: x: The x position for the trackball
//------ y: The y position for the trackball
//***********************************************
double Trackball::calcZCoordinate(const double &x, const double &y){
    double z = -1;
    double r = 1 - (x*x) -(y*y);
    if(r > 0){
        z = sqrt(r);
    }
    return z;
}
